package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.shape.Quad;
import java.util.ArrayList;

/**
 * test
 * @author normenhansen
 */
public class Main extends SimpleApplication {
    
    int quadHeight=100, quadWidth=100;//both must be greater than 10 for best result
    LivingQuad[][] quads = new LivingQuad[quadWidth][quadHeight];
    boolean update = false;

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        
        this.flyCam.setMoveSpeed(100f);

        LivingQuad tempQuad;
        
        for(int i=0; i<quadWidth; i++){
            for(int j=0; j<quadHeight; j++){
                tempQuad = new LivingQuad("Quad", new Quad(LivingQuad.TILE_SIZE, 
                                    LivingQuad.TILE_SIZE, false), i, j);
                tempQuad.setLocalTranslation(i*(LivingQuad.TILE_SIZE+.05f), j*(LivingQuad.TILE_SIZE+.05f), 0);
                
                rootNode.attachChild(tempQuad);
                quads[i][j] = tempQuad;
            }
        }
        
    }

    @Override
    public void simpleUpdate(float tpf) {
        if(update){
            update = false;
            for(int i=0; i<quadWidth; i++){
                for(int j=0; j<quadHeight; j++){
                    quads[i][j].update();
                }
            }
        }else{
            update = true;
        }
    }

    @Override
    public void simpleRender(RenderManager rm) {
        
    }
    
    public class LivingQuad extends Geometry{
        
        int locx, locy;
        boolean isAlive = false;
        boolean isNextAlive = false;
        
        final static float TILE_SIZE = .25f;
        int adjAlive = 0;
        
        private Quad tile;
        
        public LivingQuad(String name, Mesh mesh, int x, int y){
            super(name, mesh);
            locx = x;
            locy = y;
            
            tile = (Quad) mesh;
            
            if(Math.random() > .9){
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color", ColorRGBA.Green);
                setMaterial(mat);
                isAlive = true;
            }else {
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color", ColorRGBA.Black);
                setMaterial(mat);
                isAlive = false;
            }
        }
        
        public void update(){
            checkLife();
            
            isAlive = isNextAlive;
            
            if(isAlive){
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color", ColorRGBA.Green);
                setMaterial(mat);
            }else {
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setColor("Color", ColorRGBA.Black);
                setMaterial(mat);
            }
        }
        
        private void checkLife(){
            if(locx == 0 && locy == 0){
                this.calcIsLowerLeftCorner();
            }else if(locx == quadWidth-1 && locy == 0){
                this.calcIsLowerRightCorner();
            }else if(locx == 0 && locy == quadHeight-1){
                this.calcIsUpperLeftCorner();
            }else if(locx == quadWidth-1 && locy == quadHeight-1){
                this.calcIsUpperRightCorner();
            }else if(locy == 0){
                this.calcIsBottomEdge();
            }else if(locx == 0){
                this.calcIsLeftEdge();
            }else if(locx == quadWidth-1){
                this.calcIsRightEdge();
            }else if(locy == quadHeight-1){
                this.calcIsTopEdge();
            }else{
                this.calcIsInMiddle();
            }
            
            if(adjAlive < 2 || adjAlive > 3){
                isNextAlive = false;
            }/*else if(adjAlive < 4 && isAlive){
                isNextAlive = true;
            }*/else if(adjAlive == 3){
                isNextAlive = true;
            }
            
            adjAlive = 0;
            
        }
        
        public void calcIsInMiddle(){
            for(int i=0; i<8; i++) {
                switch(i){
                    case 0:
                        if (quads[locx-1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx+1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 3:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 4:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 5:
                        if (quads[locx-1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 6:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 7:
                        if (quads[locx+1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break; 
                }
            }
        }
        
        public void calcIsRightEdge(){
            for(int i=0; i<5; i++) {
                switch(i){
                    case 0:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx-1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 3:
                        if (quads[locx-1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 4:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                }
            }
        }
        
        public void calcIsLeftEdge(){
            for(int i=0; i<5; i++) {
                switch(i){
                    case 0:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx+1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 3:
                        if (quads[locx+1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 4:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                }
            }
        }
        
        public void calcIsTopEdge(){
            for(int i=0; i<5; i++) {
                switch(i){
                    case 0:
                        if (quads[locx-1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx+1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 3:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 4:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                }
            }
        }
        
        public void calcIsBottomEdge(){
            for(int i=0; i<5; i++) {
                switch(i){
                    case 0:
                        if (quads[locx-1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx+1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 3:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 4:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break;
                }
            }
        }
        
        public void calcIsUpperRightCorner(){
            for(int i=0; i<3; i++) {
                switch(i){
                    case 0:
                        if (quads[locx-1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break; 
                }
            }
        }
        
        public void calcIsUpperLeftCorner(){
            for(int i=0; i<3; i++) {
                switch(i){
                    case 0:
                        if (quads[locx+1][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy-1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break; 
                }
            }
        }
        
        public void calcIsLowerLeftCorner(){
            for(int i=0; i<3; i++) {
                switch(i){
                    case 0:
                        if (quads[locx+1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx+1][locy].isAlive()){
                            adjAlive++;
                        }
                        break; 
                }
            }
        }
        
        public void calcIsLowerRightCorner(){
            for(int i=0; i<3; i++) {
                switch(i){
                    case 0:
                        if (quads[locx-1][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 1:
                        if (quads[locx][locy+1].isAlive()){
                            adjAlive++;
                        }
                        break;
                    case 2:
                        if (quads[locx-1][locy].isAlive()){
                            adjAlive++;
                        }
                        break; 
                }
            }
        }
        
        public void setIsAlive(){
            isAlive = isNextAlive;
        }
        
        public boolean isAlive(){
            return isAlive;
        }
    }
    
}
